/**
 * 时间处理工具类
 * @description 提供时间计算、格式化、验证、冲突检测等功能
 */
export class TimeUtils {
  /**
   * 时间格式常量
   */
  static readonly TIME_FORMAT = 'HH:mm';
  static readonly TIME_FORMAT_WITH_SECONDS = 'HH:mm:ss';

  /**
   * 将时间字符串转换为分钟数
   * @param timeString 时间字符串 (HH:mm)
   * @returns 从00:00开始的分钟数
   */
  static timeToMinutes(timeString: string): number {
    if (!this.isValidTimeFormat(timeString)) {
      throw new Error(`无效的时间格式: ${timeString}`);
    }

    const [hours, minutes] = timeString.split(':').map(Number);
    return hours * 60 + minutes;
  }

  /**
   * 将分钟数转换为时间字符串
   * @param minutes 分钟数
   * @returns 时间字符串 (HH:mm)
   */
  static minutesToTime(minutes: number): string {
    if (minutes < 0 || minutes >= 24 * 60) {
      throw new Error(`无效的分钟数: ${minutes}`);
    }

    const hours = Math.floor(minutes / 60);
    const mins = minutes % 60;
    return `${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`;
  }

  /**
   * 验证时间格式是否正确
   * @param timeString 时间字符串
   * @returns 是否为有效时间格式
   */
  static isValidTimeFormat(timeString: string): boolean {
    if (!timeString || typeof timeString !== 'string') {
      return false;
    }

    const timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/;
    return timeRegex.test(timeString);
  }

  /**
   * 比较两个时间的大小
   * @param time1 时间1
   * @param time2 时间2
   * @returns -1: time1 < time2, 0: time1 = time2, 1: time1 > time2
   */
  static compareTime(time1: string, time2: string): number {
    const minutes1 = this.timeToMinutes(time1);
    const minutes2 = this.timeToMinutes(time2);

    if (minutes1 < minutes2) return -1;
    if (minutes1 > minutes2) return 1;
    return 0;
  }

  /**
   * 检查时间是否在指定范围内
   * @param time 要检查的时间
   * @param startTime 开始时间
   * @param endTime 结束时间
   * @returns 是否在范围内
   */
  static isTimeInRange(time: string, startTime: string, endTime: string): boolean {
    const timeMinutes = this.timeToMinutes(time);
    const startMinutes = this.timeToMinutes(startTime);
    const endMinutes = this.timeToMinutes(endTime);

    return timeMinutes >= startMinutes && timeMinutes <= endMinutes;
  }

  /**
   * 检查两个时间段是否重叠
   * @param start1 时间段1开始时间
   * @param end1 时间段1结束时间
   * @param start2 时间段2开始时间
   * @param end2 时间段2结束时间
   * @returns 是否重叠
   */
  static isTimeRangeOverlap(start1: string, end1: string, start2: string, end2: string): boolean {
    const start1Minutes = this.timeToMinutes(start1);
    const end1Minutes = this.timeToMinutes(end1);
    const start2Minutes = this.timeToMinutes(start2);
    const end2Minutes = this.timeToMinutes(end2);

    // 检查是否有重叠：两个时间段不重叠的条件是一个完全在另一个之前或之后
    return !(end1Minutes <= start2Minutes || end2Minutes <= start1Minutes);
  }

  /**
   * 检查两个时间段是否完全相同
   * @param start1 时间段1开始时间
   * @param end1 时间段1结束时间
   * @param start2 时间段2开始时间
   * @param end2 时间段2结束时间
   * @returns 是否完全相同
   */
  static isTimeRangeSame(start1: string, end1: string, start2: string, end2: string): boolean {
    return start1 === start2 && end1 === end2;
  }

  /**
   * 计算两个时间之间的分钟差
   * @param startTime 开始时间
   * @param endTime 结束时间
   * @returns 分钟差
   */
  static getTimeDifferenceInMinutes(startTime: string, endTime: string): number {
    const startMinutes = this.timeToMinutes(startTime);
    const endMinutes = this.timeToMinutes(endTime);
    return endMinutes - startMinutes;
  }

  /**
   * 计算时间段的持续时间（小时）
   * @param startTime 开始时间
   * @param endTime 结束时间
   * @returns 持续时间（小时）
   */
  static getDurationInHours(startTime: string, endTime: string): number {
    const minutes = this.getTimeDifferenceInMinutes(startTime, endTime);
    return minutes / 60;
  }

  /**
   * 格式化时间段为显示文本
   * @param startTime 开始时间
   * @param endTime 结束时间
   * @returns 格式化的时间段文本
   */
  static formatTimeRange(startTime: string, endTime: string): string {
    return `${startTime} - ${endTime}`;
  }

  /**
   * 格式化持续时间为显示文本
   * @param startTime 开始时间
   * @param endTime 结束时间
   * @returns 格式化的持续时间文本
   */
  static formatDuration(startTime: string, endTime: string): string {
    const minutes = this.getTimeDifferenceInMinutes(startTime, endTime);
    const hours = Math.floor(minutes / 60);
    const remainingMinutes = minutes % 60;

    if (hours === 0) {
      return `${remainingMinutes}分钟`;
    } else if (remainingMinutes === 0) {
      return `${hours}小时`;
    } else {
      return `${hours}小时${remainingMinutes}分钟`;
    }
  }

  /**
   * 在指定时间基础上添加分钟
   * @param time 基准时间
   * @param minutes 要添加的分钟数
   * @returns 新时间
   */
  static addMinutes(time: string, minutes: number): string {
    const totalMinutes = this.timeToMinutes(time) + minutes;
    
    // 处理跨天情况
    if (totalMinutes >= 24 * 60) {
      return this.minutesToTime(totalMinutes % (24 * 60));
    } else if (totalMinutes < 0) {
      return this.minutesToTime((24 * 60) + (totalMinutes % (24 * 60)));
    }
    
    return this.minutesToTime(totalMinutes);
  }

  /**
   * 在指定时间基础上减去分钟
   * @param time 基准时间
   * @param minutes 要减去的分钟数
   * @returns 新时间
   */
  static subtractMinutes(time: string, minutes: number): string {
    return this.addMinutes(time, -minutes);
  }

  /**
   * 获取时间段的中点时间
   * @param startTime 开始时间
   * @param endTime 结束时间
   * @returns 中点时间
   */
  static getMiddleTime(startTime: string, endTime: string): string {
    const startMinutes = this.timeToMinutes(startTime);
    const endMinutes = this.timeToMinutes(endTime);
    const middleMinutes = Math.floor((startMinutes + endMinutes) / 2);
    return this.minutesToTime(middleMinutes);
  }

  /**
   * 检查时间是否为整点
   * @param time 时间字符串
   * @returns 是否为整点
   */
  static isFullHour(time: string): boolean {
    return time.endsWith(':00');
  }

  /**
   * 检查时间是否为半点
   * @param time 时间字符串
   * @returns 是否为半点
   */
  static isHalfHour(time: string): boolean {
    return time.endsWith(':30');
  }

  /**
   * 将时间调整到最近的整点或半点
   * @param time 原始时间
   * @param roundUp 是否向上调整
   * @returns 调整后的时间
   */
  static roundToNearestHalfHour(time: string, roundUp: boolean = false): string {
    const minutes = this.timeToMinutes(time);
    const minutesInHour = minutes % 60;

    let adjustedMinutes: number;
    if (minutesInHour === 0 || minutesInHour === 30) {
      // 已经是整点或半点
      adjustedMinutes = minutes;
    } else if (minutesInHour <= 15) {
      // 调整到整点
      adjustedMinutes = roundUp ? minutes - minutesInHour + 30 : minutes - minutesInHour;
    } else if (minutesInHour <= 45) {
      // 调整到半点
      adjustedMinutes = roundUp ? minutes - minutesInHour + 60 : minutes - minutesInHour + 30;
    } else {
      // 调整到下一个整点
      adjustedMinutes = roundUp ? minutes - minutesInHour + 60 : minutes - minutesInHour + 30;
    }

    // 处理跨天情况
    if (adjustedMinutes >= 24 * 60) {
      adjustedMinutes = adjustedMinutes % (24 * 60);
    }

    return this.minutesToTime(adjustedMinutes);
  }

  /**
   * 生成时间选项列表
   * @param startTime 开始时间
   * @param endTime 结束时间
   * @param interval 间隔分钟数
   * @returns 时间选项列表
   */
  static generateTimeOptions(startTime: string = '00:00', endTime: string = '23:59', interval: number = 30): string[] {
    const options: string[] = [];
    const startMinutes = this.timeToMinutes(startTime);
    const endMinutes = this.timeToMinutes(endTime);

    for (let minutes = startMinutes; minutes <= endMinutes; minutes += interval) {
      options.push(this.minutesToTime(minutes));
    }

    return options;
  }

  /**
   * 获取常用的上课时间段
   * @returns 常用时间段列表
   */
  static getCommonClassTimeSlots(): Array<{ label: string; startTime: string; endTime: string }> {
    return [
      { label: '上午第一节', startTime: '08:00', endTime: '09:30' },
      { label: '上午第二节', startTime: '09:45', endTime: '11:15' },
      { label: '上午第三节', startTime: '11:30', endTime: '12:00' },
      { label: '下午第一节', startTime: '14:00', endTime: '15:30' },
      { label: '下午第二节', startTime: '15:45', endTime: '17:15' },
      { label: '下午第三节', startTime: '17:30', endTime: '19:00' },
      { label: '晚上第一节', startTime: '19:15', endTime: '20:45' },
      { label: '晚上第二节', startTime: '21:00', endTime: '22:30' }
    ];
  }

  /**
   * 检测课程时间冲突
   * @param schedules 现有课程安排列表
   * @param newSchedule 新课程安排
   * @returns 冲突检测结果
   */
  static detectTimeConflict(
    schedules: Array<{
      date: string;
      startTime: string;
      endTime: string;
      studentId: string;
      courseName?: string;
    }>,
    newSchedule: {
      date: string;
      startTime: string;
      endTime: string;
      studentId: string;
    }
  ): {
    hasConflict: boolean;
    conflicts: Array<{
      date: string;
      startTime: string;
      endTime: string;
      courseName?: string;
      conflictType: 'time_overlap' | 'same_time';
    }>;
  } {
    const conflicts: Array<{
      date: string;
      startTime: string;
      endTime: string;
      courseName?: string;
      conflictType: 'time_overlap' | 'same_time';
    }> = [];

    // 只检查同一学生同一天的课程
    const sameDaySchedules = schedules.filter(
      schedule => schedule.date === newSchedule.date && schedule.studentId === newSchedule.studentId
    );

    for (const schedule of sameDaySchedules) {
      const isSameTime = this.isTimeRangeSame(
        schedule.startTime,
        schedule.endTime,
        newSchedule.startTime,
        newSchedule.endTime
      );

      const isOverlap = this.isTimeRangeOverlap(
        schedule.startTime,
        schedule.endTime,
        newSchedule.startTime,
        newSchedule.endTime
      );

      if (isSameTime) {
        conflicts.push({
          date: schedule.date,
          startTime: schedule.startTime,
          endTime: schedule.endTime,
          courseName: schedule.courseName,
          conflictType: 'same_time'
        });
      } else if (isOverlap) {
        conflicts.push({
          date: schedule.date,
          startTime: schedule.startTime,
          endTime: schedule.endTime,
          courseName: schedule.courseName,
          conflictType: 'time_overlap'
        });
      }
    }

    return {
      hasConflict: conflicts.length > 0,
      conflicts
    };
  }
}

/**
 * 导出便捷函数
 */

/**
 * 将时间转换为分钟数
 */
export const timeToMinutes = (timeString: string) => TimeUtils.timeToMinutes(timeString);

/**
 * 将分钟数转换为时间
 */
export const minutesToTime = (minutes: number) => TimeUtils.minutesToTime(minutes);

/**
 * 验证时间格式
 */
export const isValidTimeFormat = (timeString: string) => TimeUtils.isValidTimeFormat(timeString);

/**
 * 比较时间大小
 */
export const compareTime = (time1: string, time2: string) => TimeUtils.compareTime(time1, time2);

/**
 * 检查时间段是否重叠
 */
export const isTimeRangeOverlap = (start1: string, end1: string, start2: string, end2: string) => 
  TimeUtils.isTimeRangeOverlap(start1, end1, start2, end2);

/**
 * 格式化时间段
 */
export const formatTimeRange = (startTime: string, endTime: string) => 
  TimeUtils.formatTimeRange(startTime, endTime);

/**
 * 格式化持续时间
 */
export const formatDuration = (startTime: string, endTime: string) => 
  TimeUtils.formatDuration(startTime, endTime);

/**
 * 检测时间冲突
 */
export const detectTimeConflict = (
  schedules: Array<{
    date: string;
    startTime: string;
    endTime: string;
    studentId: string;
    courseName?: string;
  }>,
  newSchedule: {
    date: string;
    startTime: string;
    endTime: string;
    studentId: string;
  }
) => TimeUtils.detectTimeConflict(schedules, newSchedule);

/**
 * 获取常用上课时间段
 */
export const getCommonClassTimeSlots = () => TimeUtils.getCommonClassTimeSlots();